#include "ThreadPool.h"

#include <chrono>
#include <iostream>
#include <thread>

using std::cout;
using std::endl;

ThreadPool::ThreadPool(size_t threadNum, size_t capa)
: _threadNum(threadNum)
, _threads()
, _capacity(capa)
, _taskQue(_capacity)
, _isExit(false)
{
}

ThreadPool::~ThreadPool()
{}

//线程池的启动与停止
void ThreadPool::start()
{
    //就是子线程的创建与启动，同时还要存放在vector中
    for(size_t idx = 0; idx < _threadNum; ++idx)
    {
        _threads.push_back(thread(&ThreadPool::doTask, this));
    }
}

void ThreadPool::stop()
{
    //只要任务队列不为空，那么主线程（线程池对象不将标志位_isExit设置为true）
    while(!_taskQue.empty())
    {
        //让主线程放弃对CPU的控制权，防止CPU空转
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    //线程池要退出来，可以将标志位设置为true
    _isExit = true;

    //唤醒所有可能在_notEmpty条件变量上睡眠的线程
    _taskQue.wakeup();

    //回收线程对象
    for(auto &th : _threads)
    {
        th.join();//让其他线程等着子线程的执行
    }
}

//添加任务与获取任务
void ThreadPool::addTask(Task &&taskcb)
{
    if(taskcb)
    {
        _taskQue.push(std::move(taskcb));
    }
}

Task ThreadPool::getTask()
{
    return _taskQue.pop();
}

//线程池交给工作线程（子线程）执行的任务
void ThreadPool::doTask()
{
    while(!_isExit)
    {
        //获取任务并执行任务
        Task taskcb = getTask();
        if(taskcb)
        {
            /* ptask->process();//执行任务,肯定会走多态,在此处是错误的 */
            //就是改变函数形态之后的MyTask中的process函数，
            //Task Taskcb = bind(&MyTask::process, ptask.get())
            taskcb();
        }
        else
        {
            cout << "nullptr == ptask" << endl;
        }
    }
}
